#include "lib.h"

#include "PerfectPairSideBet.h"
#include "bjconn.h"
#include "cardmgr.h"
#include "bjhand.h"
#include "bjgame.h"
#include "bjsaved.h"


// sidebet payout odds. 
const int32 PerfectPairSideBet::m_anPerfectPairPaytables [][3] = 
{   
    { 6, 12, 25 },      // low payout
    { 5, 15, 25 },      // medium payout
    { 5, 12, 30 }       // high payout.
};



/***************************************************************************************************
 * This method is used during the creation of a new game of Perfect Pairs.
 *
 * @param pMgr       - (in) We need this to get the ranks and suits of cards.
 * @param pConn      - (in) connection to client and database
 * @param nMaxBJBets - (in) 1 if single bet mode, 2 if in multibet mode.
 * @param anSideBets - (in) array of bet amounts the player made
 *
 ***************************************************************************************************/
PerfectPairSideBet::PerfectPairSideBet(CardMgr* pMgr, BJConnection* pConn, 
                                       int32 nMaxBJBets, int32 anSideBets[BJMAXBETS])
{
    m_pMgr = pMgr;

    m_pConn = pConn;

    m_nMaxBJBets = nMaxBJBets;

    memcpy(m_anSideBets, anSideBets, sizeof(m_anSideBets));
	
    memset(m_anSideBetPayouts, 0, sizeof(m_anSideBetPayouts));
    memset(m_anSideBetWinType, 0, sizeof(m_anSideBetWinType));

}


/***************************************************************************************************
 * This method is used when restoring the state of a saved game of blackjack
 *
 * @param pMgr       - (in) We need this to get the ranks and suits of cards.
 * @param pConn      - (in) connection to client and database
 * @param pSaved     - (in) contains the info we need to restore the state of the sidebet.
 *
 ***************************************************************************************************/
PerfectPairSideBet::PerfectPairSideBet(CardMgr *pMgr, BJConnection* pConn, BJSavedGame* pSaved)
{
    m_pMgr = pMgr;

    m_pConn = pConn;

    memset(m_anSideBets, 0, sizeof(m_anSideBets));
    memset(m_anSideBetPayouts, 0, sizeof(m_anSideBetPayouts));
    memset(m_anSideBetWinType, 0, sizeof(m_anSideBetWinType));

    m_nMaxBJBets = pSaved->maxBJBets;

    for(int nI=0;nI<m_nMaxBJBets;++nI)
    {
        m_anSideBets[nI]       = pSaved->BJBets[nI].nPPSideBet;
        m_anSideBetPayouts[nI] = pSaved->BJBets[nI].nPPSideBetPayout;
        m_anSideBetWinType[nI] = pSaved->BJBets[nI].nPPWinType;
    }
}



/***************************************************************************************************
 * This method is called by BJGame after the first two player cards are dealt.  Perfect Pairs 
 * then calculates the outcome of the player's bets and the amount of money won, if any.  The 
 * game state in the database is then updated with these results.
 *
 * @param  pcGID   - (in) The gamenum this sidebet is associated with...needed for DB update
 * @param  phand   - (in) the hand containing the two cards the player was dealt
 * @param  nBJBet  - (in) for multibet blackjack indicates which player hand we're looking at.
 *
 ***************************************************************************************************/
void PerfectPairSideBet::calculateDealResults(char *pcGID, BJHand *phand, int32 nBJBet)
{
    m_anSideBetPayouts[nBJBet] = 0;
    uint8 ucCard1 = phand->getCardAt(0);
    uint8 ucCard2 = phand->getCardAt(1);

    PerfectPairWinTypes ePairType = NO_PAIR;  // assume that the player has lost.

    // if the two cards are the same rank, then we have a pair at least.
    if(m_pMgr->getRank(ucCard1)==m_pMgr->getRank(ucCard2))
    {
        // now, is it a mixed, colored, or perfect pair?
        uint8 ucSuit1 = m_pMgr->getSuit(ucCard1);
        uint8 ucSuit2 = m_pMgr->getSuit(ucCard2);

        if(ucSuit1==ucSuit2)    
        {
            ePairType = PERFECT_PAIR;
            m_anSideBetPayouts[nBJBet] = m_anSideBets[nBJBet] * m_anPerfectPairPaytables[m_pConn->getSideBetPaytable()][2];
        }
        else if( ((ucSuit1&0x20)!=0) == ((ucSuit2&0x20)!=0))
        {
            ePairType = COLORED_PAIR;
            m_anSideBetPayouts[nBJBet] = m_anSideBets[nBJBet] * m_anPerfectPairPaytables[m_pConn->getSideBetPaytable()][1];
        }
        else
        {
            ePairType = MIXED_PAIR;
            m_anSideBetPayouts[nBJBet] = m_anSideBets[nBJBet] * m_anPerfectPairPaytables[m_pConn->getSideBetPaytable()][0];
        }
    }

    m_anSideBetWinType[nBJBet] = (int32) ePairType;

    if(m_anSideBets[nBJBet]>0)
    {
        // if the player made a bet on this hand, store the results in the database.
        // if the player didn't make a bet, then there's nothing to update in the DB so just continue.
        int32 nBalance=0;
        m_pConn->trackSideBetResult(pcGID, (uint8) ePairType, m_anSideBetPayouts[nBJBet], &nBalance);
    }
}


/***************************************************************************************************
 * This method is used to send the calculated win/loss results for the sidebet down to the client.
 * They are just added to the 'D' deal message.
 ***************************************************************************************************/
void PerfectPairSideBet::sendResults()
{
    for( int32 nI=0; nI<BJMAXBETS; ++nI )
    {
	    m_pConn->SENDINT4(m_anSideBetPayouts[nI]);
        m_pConn->SENDINT4(m_anSideBetWinType[nI]);
    }
}

/***************************************************************************************************
 * This method is called when a saved game is being restored.  We put the state of the sidebet into
 * the msg buffer being sent down to the client.
 ***************************************************************************************************/
void PerfectPairSideBet::sendSaveState()
{
    for( int32 nI=0; nI<BJMAXBETS; ++nI )
    {
        m_pConn->SENDINT4(m_anSideBets[nI]);
	    m_pConn->SENDINT4(m_anSideBetPayouts[nI]);
        m_pConn->SENDINT4(m_anSideBetWinType[nI]);
    }
}
